package com.ttdevs.socket.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import com.ttdevs.socket.ISocket;
import com.ttdevs.socket.util.BaseThread;
import com.ttdevs.socket.util.IPConfig;
import com.ttdevs.socket.util.SocketConfig;
import com.ttdevs.socket.util.SocketLog;

public class SocketUDPImp extends BaseThread implements ISocket {

	private UDPSender udpSender;
	private UDPReceiver udpReceiver;
	private BlockingQueue<DatagramPacket> senderQueue;
	private BlockingQueue<DatagramPacket> receiverQueue;
	private OnSocketListener mListener;
	private DatagramSocket mSocket;
	private IPConfig mIPConfig;

	public SocketUDPImp() {
		senderQueue = new ArrayBlockingQueue<DatagramPacket>(SocketConfig.SENDQUEUESIZE);
		receiverQueue = new ArrayBlockingQueue<DatagramPacket>(SocketConfig.RECEIVEQUEUESIZE);
	}

	@Override
	public boolean connect(IPConfig ipConfig, OnSocketListener listener) {
		if (listener == null) {
			return false;
		}
		mListener = listener;
		mIPConfig = ipConfig;
		try {
			mSocket = new DatagramSocket();
		} catch (SocketException e) {
			SocketLog.d("udp connect init error: %s", e.getMessage());
			return false;
		}
		
		udpSender = new UDPSender(senderQueue, this, mSocket);
		udpSender.start();
		
		udpReceiver = new UDPReceiver(receiverQueue, this, mSocket);
		udpReceiver.start();

		this.start();
		return true;
	}

	@Override
	public void close(boolean isNotify, boolean isByServer) {
		mSocket.close();
		if (isNotify) {
			mListener.onClose(isByServer, this);
		}
	}

	@Override
	public boolean sendData(byte[] data) {
		if (data != null) {
			try {
				senderQueue.put(new DatagramPacket(data, data.length, mIPConfig.getIp(), mIPConfig.getPort()));
			} catch (InterruptedException e) {
				SocketLog.d("udp sender: %s", e.getMessage());
				return false;
			} catch (UnknownHostException e) {
				SocketLog.d("udp sender: %s", e.getMessage());
				return false;
			}
			return true;
		}
		return false;
	}

	@Override
	public void execute() {
		try {
			DatagramPacket packet = receiverQueue.take();
			byte[] data = packet.getData();
			if (data != null) {
				mListener.onRead(data, this);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
			close(true, false);
			quit();
		}
	}
}
